<template>
  <div style="width: 100%;height: 100%">
    <div class="map" id="map"></div>
    <div v-if="showPopup === true" class="popup">
      弹窗弹窗弹窗弹窗弹窗弹窗弹窗
    </div>
  </div>
</template>

<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import OSM from 'ol/source/OSM';
import Feature from 'ol/Feature';
import { fromLonLat } from "ol/proj";
import VectorSource from 'ol/source/Vector';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ'
import Point from 'ol/geom/Point';
import { Fill, Stroke, Icon, Style, Circle } from 'ol/style'
// import markerImg from '@/assets/img/markericon.png'
import { getPointData } from "@/api/map";
import LineString from "ol/geom/LineString";
import RegularShape from 'ol/style/RegularShape';
import { defaults as defaultControls } from 'ol/control';

export default {
  name: "openlayersMap",
  data() {
    return {
      mapObj: null,
      mapDom: null,
      mapPointList: [],
      pointLayerSource: null,
      pointLayer: null,
      mapLineList: [],
      lineLayerSource: null,
      lineLayer: null,
      // markerIcon: markerImg
      pointData: [],
      lineData: [],

      showPopup: false,
      popupContent: '',
      selectedFeature: null
    }
  },
  mounted() {
    // this.getMap()
    this.initMap()
    this.addPoint()
  },
  methods: {
    // 获取后台数据
    getMap() {
      // 获取点位数据
      getPointData().then((res) => {
        if (res.code === 200) {
          this.pointData = res.data
          // 加载地理坐标
          this.addPoint()
        }
      })
      // 获取连接线数据
      getLineData().then((res) => {
        if (res.code === 200) {
          this.lineData = res.data
          // 加载地理线
          this.addLine()
        }
      })

    },

    // 清除地图 某些情况 地图容器会存在两个 导致地图无法正常显示 这个问题折腾了我半天。
    // 找了半天官方貌似也没有提供 对应的 api，自己动手了。
    mapClear() {
      if (this.mapDom) {
        this.mapDom.innerHTML = ''
        this.mapDom = null
      }
    },

    // 初始化地图
    initMap() {
      // 先尝试清除
      this.mapClear()
      // 获取地图容器
      this.mapDom = document.getElementById('map')
      // 初始化地图配置
      this.mapObj = new Map({
        target: this.mapDom, // 地图容器
        view: new View({
          zoom: 6, // 缩放
          projection: 'EPSG:4326', // 坐标系
          center: [100.990969, 36.635013], // 地图中心点
        }),
        //加载控件到地图容器中
        controls: defaultControls({
          zoom: false,
          rotate: false,
          attribution: false
        }),
      })
      // this.mapDom.on('click', function (evt) {
      //   console.log(evt)
      // });
      // 添加一个使用离线瓦片地图的层
      const offlineMapLayer = new TileLayer({
        className: "baseLayerClass",
        source: new XYZ({
          // url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}",
          url: "https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
        })
        // source: new OSM()	//OSM地图
      })
      // 将图层添加到地图
      this.mapObj.addLayer(offlineMapLayer)
    },

    // 添加地理坐标
    addPoint() {
      this.delPointAll()

      // const convertedArray = this.pointData.map(item => ({
      //   longitude: parseFloat(item.longitude),
      //   latitude: parseFloat(item.latitude)
      // }));

      const convertedArray = [
        { id: 1, longitude: 118.150, latitude: 34.030 },
        { id: 2, longitude: 120.210, latitude: 31.850 },
        { id: 3, longitude: 117.380, latitude: 36.120 },
        { id: 4, longitude: 116.280, latitude: 32.150 },
        { id: 5, longitude: 117.260, latitude: 29.660 },
      ]

      convertedArray.map(item => {
        // 创建点
        const point = new Feature({
          geometry: new Point([item.longitude, item.latitude]),
          data: item
        })

        // 点的样式
        const iconStyle = new Style({
          // image: new Icon({
          //   color: '#ffffff',
          //   crossOrigin: 'anonymous',
          //   src: this.markerIcon,
          // }),
          image: new Circle({
            radius: 10,
            fill: new Fill({
              color: "#0D98BA"
            })
          })
        })
        // 设置样式
        point.setStyle(iconStyle)
        // 保存到数据  方便删除
        this.mapPointList.push(point)
      })
      // console.log('this.mapPointList', this.mapPointList);

      // 创建geojson据源
      this.pointLayerSource = new VectorSource({ features: this.mapPointList })
      // 创建图层 并加载数据
      this.pointLayer = new VectorLayer({ source: this.pointLayerSource })
      // 将图层添加地图上
      this.mapObj.addLayer(this.pointLayer)

      // this.mapObj.on('click', (event) => {
      //   // console.log('event', event);
      //   // console.log('Map clicked at:', event.pixel);
      //   this.mapClickHandler(event);
      // });

      this.singleclick();
    },

    // 地理点位删除
    delPointAll() {
      // 判断 删除的数据源是否存在
      if (this.pointLayerSource) {
        // 遍历删除
        this.mapPointList.map(item => {
          this.pointLayerSource.removeFeature(item)
        })

        // 删除图层 重置数据
        this.mapObj.removeLayer(this.pointLayer)
        this.pointLayerSource = null
        this.pointLayer = null
        this.mapPointList = []
      }
    },

    // 添加地理线
    addLine() {
      // 地理线数组
      // const lineData = [
      //   [[117.990969, 36.635013], [117.348611, 37.581141]],
      //   [[117.990969, 36.635013], [117.648611, 35.581141]],
      //   [[117.990969, 36.635013], [117.990969, 36.635013]]
      // ];

      this.lineData.map(item => {
        const lineCoordinates = item.map(coordinate => [coordinate[0], coordinate[1]]);
        const lineGeometry = new LineString(lineCoordinates);

        const radius = 10;
        // 线的样式 
        const lineStyle = new Style({
          stroke: new Stroke({
            color: 'rgba(0, 0, 255, 0.7)', // 蓝色半透明线
            width: 5,
            lineDash: [6, 8], // 虚线样式
            lineCap: 'round', // 线帽样式
            lineJoin: 'round' // 线连接样式
          }),
          image: new RegularShape({
            points: 60, // 设置点数使其接近圆形
            radius: radius,
            radius2: radius,
            angle: Math.PI, // 弧度值，这里设置为半圆
            fill: new Fill({
              color: 'rgba(0, 0, 255, 0.7)'
            })
          })
        });

        // 创建线的要素 
        const lineFeature = new Feature({
          geometry: lineGeometry,
          data: item
        });

        // 设置线的样式
        lineFeature.setStyle(lineStyle);

        // 将线的要素添加到地图的线图层中
        this.mapLineList.push(lineFeature);
      });


      // 创建线的数据源
      this.lineLayerSource = new VectorSource({ features: this.mapLineList });
      // 创建线的图层
      this.lineLayer = new VectorLayer({ source: this.lineLayerSource });
      // 将线的图层添加到地图上
      this.mapObj.addLayer(this.lineLayer);
    },

    mapClickHandler(event) {
      let _that = this
      // 使用 `forEachFeatureAtPixel` 方法来获取点击位置处的地图要素（feature）
      // console.log('event', event);
      // console.log('Map clicked at:', event.pixel);
      const feature = _that.mapObj.forEachFeatureAtPixel(event.pixel, function (feature) {
        return feature;
      });
      // console.log('feature', feature);


      // 检查获取到的要素是否存在并且其几何类型是否为 'Point'
      if (feature && feature.getGeometry().getType() === 'Point') {
        // 设置 `showPopup` 为 true，以显示弹出窗口
        _that.showPopup = true;
        console.log('_that.showPopup', _that.showPopup);

        // 保存选中的要素
        _that.selectedFeature = feature;

        // 设置弹出窗口的内容，显示经度和纬度信息
        _that.popupContent = `经度: ${feature.get('data').longitude}, 纬度: ${feature.get('data').latitude}`;
      } else {
        // 如果没有找到要素或者要素类型不是 'Point'，则隐藏弹出窗口并清除选中要素
        _that.showPopup = false;
        // console.log('_that.showPopup123123', _that.showPopup);

        _that.selectedFeature = null;
      }
    },

    singleclick() {
      // 点击
      this.openMap.on("singleclick", (e) => {
        // 判断是否点击在点上
        let feature = this.openMap.forEachFeatureAtPixel(
          e.pixel,
          (feature) => feature
        );
        console.log(feature);
        if (feature) {
          this.shopPopup = true;
          // 设置弹窗位置
          let coordinates = feature.getGeometry().getCoordinates();
          this.popup.setPosition(coordinates);
        } else {
          this.shopPopup = false;
        }
      });
    },
  },
  beforeDestroy() {
    this.mapClear()
  },
}

</script>

<style scoped>
.map {
  width: 100%;
  height: 100%;
}

.popup {
  position: absolute;
  top: 10px;
  left: 10px;
  background: white;
  padding: 10px;
  border-radius: 3px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
</style>
